package com.scs.application.modules.dept.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.base.entity.Matr;
import com.scs.application.modules.base.entity.MatrUnit;
import com.scs.application.modules.base.mapper.MatrMapper;
import com.scs.application.modules.base.service.MatrUnitService;
import com.scs.application.modules.base.util.CommonService;
import com.scs.application.modules.dept.entity.DeptReturn;
import com.scs.application.modules.dept.entity.DeptReturnItem;
import com.scs.application.modules.dept.mapper.DeptReturnItemMapper;
import com.scs.application.modules.dept.mapper.DeptReturnMapper;
import com.scs.application.modules.dept.service.DeptReturnItemService;
import com.scs.application.modules.finance.service.BillItemService;
import com.scs.application.modules.purchase.enums.PurchaseType;
import com.scs.application.modules.wm.entity.Dist;
import com.scs.application.modules.wm.entity.Stock;
import com.scs.application.modules.wm.entity.TertiaryStock;
import com.scs.application.modules.wm.mapper.DistItemMapper;
import com.scs.application.modules.wm.mapper.DistMapper;
import com.scs.application.modules.wm.mapper.TertiaryStockMapper;
import com.scs.application.modules.wm.service.StockService;
import com.scs.application.modules.wm.utils.StockCommonService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 */
@Service
public class DeptReturnItemServiceImpl extends BaseServiceImpl<DeptReturnItemMapper, DeptReturnItem> implements DeptReturnItemService {
    @Autowired
    private StockService stockService;

    @Autowired
    private DeptReturnMapper deptReturnMapper;

    @Autowired
    private DistMapper distMapper;

    @Autowired
    private DistItemMapper distItemMapper;

    @Autowired
    private MatrUnitService matrUnitService;

    @Autowired
    private BillItemService billItemService;

    @Resource
    private MatrMapper matrMapper;

    @Resource
    private TertiaryStockMapper tertiaryStockMapper;

    /**
     * 扫描入退库单
     *
     * @param deptReturnId
     * @param uniqueCode
     */
    @Override
    public void addByScan(String deptReturnId, String uniqueCode, String deptId) {
        List<Stock> stockList = stockService.getStockListByUniqueCode(uniqueCode);
        List<DeptReturnItem> deptReturnItemList=new ArrayList<>();
        for(Stock stock:stockList){
            if (stock == null) {
                throw new BusinessException(String.format("在库存中未找到%s相关的耗材", uniqueCode));
            }
            if (stock.getSkuQty() > 0) {
                throw new BusinessException("在库存中数量大于0");
            }


            List<DeptReturn> deptReturnList = deptReturnMapper.getNoAuditByUnq(uniqueCode);
            if (deptReturnList != null && deptReturnList.size() > 0) {
                throw new BusinessException(String.format("%s相关的耗材已添加至退库单[%s]，并在审核中", uniqueCode,deptReturnList.get(0).getBusKey()));
            }
            //判断是否科室申请过,必须是配送至科室的耗材才可以退库
            List<Dist> dists = distMapper.getDistByStock(stock.getId());
            if (dists == null || dists.size() < 1) {
                throw new BusinessException("没有找到该耗材的配送记录，不能退库");
            }
            List<Dist> distSn = distMapper.getDistBySn(stock.getSn(), deptId);
            if (distSn == null || distSn.size() < 1) {
                throw new BusinessException("没有找到该科室的配送记录，不能退库");
            }

            //包装转换
            List<MatrUnit> matrUnitList = matrUnitService.list(new QueryWrapper<MatrUnit>().eq("matr_id", stock.getMatrId()).eq("unit", stock.getPackageUnit()));
            if (matrUnitList == null || matrUnitList.size() < 1) {
                throw new BusinessException("未找到耗材【" + stock.getMatrName() + "】包装单位【" + stock.getPackageUnit() + "】，请联系运营人员检查耗材属性");
            }
            if (matrUnitList.size() > 1) {
                throw new BusinessException("耗材【" + stock.getMatrName() + "】找到多个包装单位【" + stock.getPackageUnit() + "】，请联系运营人员检查耗材属性");
            }
            double SkuQty = matrUnitList.get(0).getRate();

            Matr matr = matrMapper.selectById(stock.getMatrId());
            if (PurchaseType.REAGENT.getKey().equals(matr.getBaseType())) {
                TertiaryStock tertiaryStock = tertiaryStockMapper.selectOne(Wrappers.<TertiaryStock>query().eq("sn", uniqueCode));
                if (tertiaryStock == null) {
                    throw new BusinessException("未找到试剂三级库库存，请确认消耗的试剂来源是否正确");
                } else if (tertiaryStock.getPackageQty() == 0) {
                    throw new BusinessException("该试剂已经被消耗，不能退库");
                }
            }

//        CommonService.checkDeptReturn(stock.getSn(),SkuQty,deptId,null);

            DeptReturnItem deptReturnItem = new DeptReturnItem();
            BeanUtils.copyProperties(stock, deptReturnItem);
            deptReturnItem.setStockId(stock.getId())
                    .setDeptReturnId(deptReturnId)
                    //初试退库数量设为1
                    .setPackageQty(1d)
                    .setId(null); //ID不复制



            deptReturnItem.setPackageQty(1d).setSkuQty(SkuQty);
            deptReturnItem.setAmount(SkuQty * deptReturnItem.getSkuPrice());
            deptReturnItemList.add(deptReturnItem);
        }

        super.saveBatch(deptReturnItemList,1000);
//        super.save(deptReturnItem);
        calculateReturnPrice(deptReturnId);
    }

    /*批量选择*/
    @Override
    public void addBySelect(Map<String, Object> map) {
        //转list
        List<String> listSn = (List<String>) map.get("listSn");
        String deptReturnId = (String) map.get("deptReturnId");
        String deptId = (String) map.get("deptId");
        deptReturnBatch(deptReturnId,deptId,listSn);
        /*for (int i = 0; i<listSn.size(); i++) {
            addByScan(deptReturnId, listSn.get(i), deptId);
        }*/
    }

    /**
     * 科室批量退货
     * */
    public void deptReturnBatch(String deptReturnId, String deptId, List<String> snList) {
        String msgPre = "科室批量退货失败，原因：";
        if (StringUtils.isBlank(deptReturnId)) throw new BusinessException(msgPre+"deptReturnId 为空");
        if (StringUtils.isBlank(deptId)) throw new BusinessException(msgPre+"deptId 为空");
        if (snList == null || snList.size() < 1) throw new BusinessException(msgPre+"snList 为空");

        //1、snList是否重复
        snList.stream().forEach(ob1 -> {
            long count = snList.stream().filter(ob2 -> ob2.equals(ob1)).count();
            if (count > 1) throw new BusinessException(msgPre+"唯一码【%s】输入了%s次", ob1, count);
        });

        //2、库存查找
        List<Stock> stocks = StockCommonService.listStockWithZero(Wrappers.<Stock>query().in("sn",snList),null);
        if (stocks == null || stocks.size() < 1) throw new BusinessException(msgPre+"未找到相关库存");
        //21、库存校验,有无库存记录
        if (stocks.size() != snList.size()){
            List<String> snListNoExist = snList.stream().filter(ob1 -> stocks.stream().noneMatch(ob2 -> ob1.equals(ob2.getSn())))
                    .collect(Collectors.toList());
            throw new BusinessException(msgPre+"唯一码【%s】未找到相关库存记录", snListNoExist.get(0));
        }

        //3.库存数量>0
        List<String> list = stocks.stream().filter(o -> o.getSkuQty() > 0).map(e -> e.getId())
                .collect(Collectors.toList());
        if(list.size()>0){
            throw new BusinessException(msgPre+"唯一码【%s】在库存中数量大于0",list);
        }
        List<DeptReturnItem> deptReturnItemList = new ArrayList<>();
        for(Stock stock : stocks){
            if (super.list(new QueryWrapper<DeptReturnItem>().eq("dept_return_id", deptReturnId).eq("stock_id", stock.getId())).size() > 0) {
                throw new BusinessException(msgPre+String.format("%s相关的耗材已添加至退库单中", stock.getSn()));
            }
            //判断是否科室申请过,必须是配送至科室的耗材才可以退库
            List<Dist> dists = distMapper.getDistByStock(stock.getId());
            if (dists == null || dists.size() < 1) {
                throw new BusinessException(msgPre+"没有找到该耗材的配送记录，不能退库");
            }
            List<Dist> distSn = distMapper.getDistBySn(stock.getSn(), deptId);
            if (distSn == null || distSn.size() < 1) {
                throw new BusinessException(msgPre+"没有找到该科室的配送记录，不能退库");
            }

            //包装转换
            List<MatrUnit> matrUnitList = matrUnitService.list(new QueryWrapper<MatrUnit>().eq("matr_id", stock.getMatrId()).eq("unit", stock.getPackageUnit()));
            if (matrUnitList == null || matrUnitList.size() < 1)
                throw new BusinessException(msgPre+"未找到耗材【" + stock.getMatrName() + "】包装单位【" + stock.getPackageUnit() + "】，请联系运营人员检查耗材属性");
            if (matrUnitList.size() > 1)
                throw new BusinessException(msgPre+"耗材【" + stock.getMatrName() + "】找到多个包装单位【" + stock.getPackageUnit() + "】，请联系运营人员检查耗材属性");
            double SkuQty = matrUnitList.get(0).getRate();

//            CommonService.checkDeptReturn(stock.getSn(),SkuQty,deptId,null);

            DeptReturnItem deptReturnItem = new DeptReturnItem();
            BeanUtils.copyProperties(stock, deptReturnItem);
            deptReturnItem.setStockId(stock.getId())
                    .setDeptReturnId(deptReturnId)
                    //初试退库数量设为1
                    .setPackageQty(1d)
                    .setId(null); //ID不复制
            deptReturnItem.setPackageQty(1d).setSkuQty(SkuQty);
            deptReturnItem.setAmount(SkuQty * deptReturnItem.getSkuPrice());
            deptReturnItemList.add(deptReturnItem);
        }
        super.saveBatch(deptReturnItemList);
        calculateReturnPrice(deptReturnId);
    }

    /**
     * 计算退库单价格
     *
     * @param deptReturnId
     */
    private void calculateReturnPrice(String deptReturnId) {
        deptReturnMapper.updateDeptReturnAmount(deptReturnId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(DeptReturnItem deptReturnItem) {

        DeptReturn deptReturn = deptReturnMapper.selectById(deptReturnItem.getDeptReturnId());
        CommonService.checkDeptReturn(deptReturnItem.getSn(), deptReturnItem.getSkuQty(), deptReturn.getDeptId(), deptReturnItem,deptReturn);
        List<MatrUnit> list = matrUnitService.list(Wrappers.<MatrUnit>query().eq("matr_id", deptReturnItem.getMatrId())
                .eq("rate", deptReturnItem.getSkuQty()));

        if (list.isEmpty()) {
            double skuQty = Math.abs(deptReturnItem.getSkuQty());
            if (skuQty < 0) throw new BusinessException("明细保存失败！<br>单品数量【%s】要大于0", skuQty);
            MatrUnit matrUnitBase = matrUnitService.getOne(Wrappers.<MatrUnit>query().eq("matr_id", deptReturnItem.getMatrId()).eq("flag_base", 1));
            String unitNew = skuQty + matrUnitBase.getUnit();

            MatrUnit matrUnit = matrUnitService.getOne(Wrappers.<MatrUnit>query().eq("matr_id", deptReturnItem.getMatrId())
                    .eq("unit", unitNew), false);
            if (matrUnit == null) {
                matrUnit = new MatrUnit();
                matrUnit.setMatrId(deptReturnItem.getMatrId()).setFlagDisabled(true).setUnit(skuQty + "" + matrUnitBase.getUnit()).setPrice(deptReturnItem.getSkuPrice() * skuQty).setRate(skuQty).setFlagHide(true);
                matrUnitService.save(matrUnit);
            }
            deptReturnItem.setPackageUnit(matrUnit.getUnit());
        }else {
            deptReturnItem.setPackageUnit(list.get(0).getUnit());
        }

        boolean boolResult = super.saveOrUpdate(deptReturnItem);
        if (boolResult) { //重刷一下订单总价
            calculateReturnPrice(deptReturnItem.getDeptReturnId());
        }
        return boolResult;
    }

    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        List<String> distIds = this.listObjs(Wrappers.<DeptReturnItem>query()
                        .select("dept_return_id").in("id", idList).groupBy("dept_return_id"),
                v -> v.toString());
        Boolean boolResult = this.removeByIds(idList);
        if (boolResult && distIds.size() > 0) { //重刷一下订单总价
            calculateReturnPrice(distIds.get(0));
        }
        return boolResult;
    }


}
